import runtimeType from '../../sys/runtimeType';
import config from '../../sys/config';
import http from '../http';
import queue from '../queue';
import calldeal from '../calldeal';
import { showLoading } from '../prompt';
import toQueryString from '../../data/toQueryString';

/**
 * 【异步方法】request接口请求
 * @description request接口请求，参数详情请查看配置文件focus.config.js
 * @param parameter 方法参数
 */
function request(parameter) {
    
    // ------------------------------------------------ 参数预处理
    // 获取当前运行环境
    let runType = runtimeType();
    // 获取配置文件中的request设置信息
    let config_file = config('get').network;
    // 合并 配置文件参数、主动传入参数
    let config_result = Object.assign({}, config_file, parameter);
    // 传递参数：请求方式method 大写
    config_result["method"] = config_result["method"].toUpperCase();
    // 最终请求地址 = 请求地址头 + api地址
    if (config_result["openHttphead"] == true) { config_result["url"] = http('get') + config_result["url"]; }
    
    // ------------------------------------------------ 通用调用事件
    /** 成功/失败回调逻辑处理，参数：data_backC-要回调的数据 */
    function deal_callback(data_backC) {
        // 如果是请求成功
        if (data_backC.isSuccess == true) {
            // 全局的成功方法调用结果
            let result_fileSuccess = true;
            // 配置文件成功方法
            if (config_file && config_file.success) { result_fileSuccess = config_file.success(data_backC); }
            // 主动参数的失败方法
            if (result_fileSuccess===false && parameter && parameter.fail) { parameter.fail(data_backC); }
            // 主动参数的成功方法
            else if (parameter && parameter.success) { parameter.success(data_backC); }
        }
        // 如果是请求失败
        else {
            // 全局的失败方法调用结果
            let result_fileFail = true;
            // 配置文件失败方法
            if (config_file && config_file.fail) { result_fileFail = config_file.fail(data_backC); }
            // 主动参数的失败方法
            if (result_fileFail!==false && parameter && parameter.fail) { parameter.fail(data_backC); }
        }
    };
    
    // ------------------------------------------------ 绿色通道判定
    // 是否允许请求通过
    let isCanReq = false;
    // 绿色通道直接请求
    if (config_result["openGreen"] == true) { isCanReq = true; }
    else {
        // 队列不拥挤也可请求
        isCanReq = queue('add', config_result["url"]);
        // 如果是拥挤状态，报错提醒
        if (isCanReq != true)
        {
            // 获取接口请求结果对象
            let data_back = calldeal(config_result, 0, {}, null, 'queue');
            // 回调逻辑处理
            deal_callback(data_back);
        }
    }
    
    // ------------------------------------------------ 请求方法调用
    // 允许状态，才执行
    if (isCanReq == true)
    {
        // 显示"请求中"提示弹框
        if (config_result["loadingText"] != null) { showLoading(config_result["loadingText"], config_result["openWait"]); }
        
        // ------------------------------------------------ header请求头
        // 要传递请求头 编辑
        let req_header = {};
        // 1. 添加content-type
        if (config_result["method"] == "POST") {
            if (config_result["contentType"] == 1) { req_header['Content-Type'] = 'application/json'; }
            else if (config_result["contentType"] == 2) { req_header['Content-Type'] = 'application/x-www-form-urlencoded'; }
        }
        // 2. 配置文件header加入到此数据
        if (config_file["header"]) { for (let key in config_file["header"]) { req_header[key] = config_file.header[key]; } }
        // 3. 主动传递参数的header覆盖到此数据
        if (config_result["header"]) { for (let key in config_result["header"]) { req_header[key] = config_result.header[key]; } }
        
        // ------------------------------------------------ 地址栏传输数据
        // 请求地址取出
        let str_url_api = config_result["url"];
        // 地址栏数据添加
        for (let key in config_result["pathData"]) { str_url_api += '/' + config_result.pathData[key]; }
        
        // ------------------------------------------------ 调用接口请求api
        // 如果是“非UNI”环境
        if (runType == 'NOT-UNI')
        {
            // 要发送的数据
            let str_sendData = null;
            // get请求时，要在请求地址后面添加发送的参数
            if (config_result["method"] == "GET") {
                // 将数据转换为名称/值对编码字符串
                let str_query = toQueryString(config_result["data"]);
                // 如果转换成功
                if (str_query) { str_url_api = str_url_api + '?' + str_query; }
            }
            // 当不是get请求的时候，要把参数放到请求体里面
            else if (typeof (config_result["data"]) == "object") {
                // 请求参数 要以字符串形式 传递到send方法中
                str_sendData = JSON.stringify(config_result["data"]);
            }
            // 其它情况
            else {
                // 直接发送传入的data数据
                str_sendData = config_result["data"];
            }

            // 创建 XMLHttpRequest 对象
            let xhr = new XMLHttpRequest();
            // 初始化实例对象
            xhr.open(config_result["method"], str_url_api, true);
            // 请求头数据赋值
            for (let k in req_header) { xhr.setRequestHeader(k, req_header[k]); }
            // 指定请求超时时间
            xhr.timeout = config_result["timeout"];
            // 接收完服务器返回数据后，进行的数据类型处理方式
            xhr.responseType = config_result["responseType"];

            // 获取响应头公共方法
            let fun_getResponseHeader = () => {
                // 结果响应头
                let obj_resHeaders = {};
                // 获取响应头
                let str_resHeaders = xhr.getAllResponseHeaders();
                // 如果存在响应头
                if (str_resHeaders) {
                    // 将响应头转换为数组
                    var arr_resHeaders = str_resHeaders.trim().split(/[\r\n]+/);
                    // 循环响应头数组
                    arr_resHeaders.forEach((line) => {
                        // 按照冒号再分割
                        var parts = line.split(': ');
                        // 头的名称
                        var header = parts.shift();
                        // 头的值
                        var value = parts.join(': ');
                        // 将头添加到结果对象
                        obj_resHeaders[header] = value;
                    });
                }
                // 返回处理后的响应头
                return obj_resHeaders;
            };
            
            // 请求超时监听
            xhr.addEventListener('timeout', () => {
                // 获取响应头
                let obj_resHeaders = fun_getResponseHeader();
                // 获取接口请求结果对象
                let data_back = calldeal(config_result, 0, obj_resHeaders, null, 'timeout');
                // 回调逻辑处理
                deal_callback(data_back);
            });
            // 请求失败监听
            xhr.addEventListener('error', () => {
                // 获取响应头
                let obj_resHeaders = fun_getResponseHeader();
                // 获取接口请求结果对象
                let data_back = calldeal(config_result, xhr.status, obj_resHeaders, xhr.response);
                // 回调逻辑处理
                deal_callback(data_back);
            });
            // 请求成功监听
            xhr.addEventListener('load', () => {
                // 获取响应头
                let obj_resHeaders = fun_getResponseHeader();
                // 获取接口请求结果对象
                let data_back = calldeal(config_result, xhr.status, obj_resHeaders, xhr.response);
                // 回调逻辑处理
                deal_callback(data_back);
            });
            
            // 发送请求
            xhr.send(str_sendData);
        }
        // 如果是UNI环境
        else {
            // 调用请求api
            uni.request({
                method: config_result["method"],
                url: str_url_api,
                data: config_result["data"],
                header: req_header,
                timeout: config_result["timeout"],
                dataType: 'json',
                responseType: config_result["responseType"],
                fail: (resD) => {
                    // 获取接口请求结果对象
                    let data_back = calldeal(config_result, 0, resD.header, resD, 'unifail');
                    // 回调逻辑处理
                    deal_callback(data_back);
                },
                success: (resD) => {
                    // 获取接口请求结果对象
                    let data_back = calldeal(config_result, resD.statusCode, resD.header, resD.data);
                    // 回调逻辑处理
                    deal_callback(data_back);
                }
            });
        }
        
    }
    
}

export default request;